﻿using Engine;
using Engine.Audio;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;

namespace Game
{
    /// <summary>
    /// 数据处理 
    /// </summary>
    public class DataHandle
    {
        public static Color[] ColorList = new Color[]
        {
            new Color(255, 255, 255, 255),
            new Color(181, 255, 255, 255),
            new Color(255, 181, 255, 255),
            new Color(160, 181, 255, 255),
            new Color(255, 240, 160, 255),
            new Color(181, 255, 181, 255),
            new Color(255, 181, 160, 255),
            new Color(181, 181, 181, 255),
            new Color(112, 112, 112, 255),
            new Color(32, 112, 112, 255),
            new Color(70, 20, 70, 255),
            new Color(26, 52, 128, 255),
            new Color(87, 54, 31, 255),
            new Color(24, 116, 24, 255),
            new Color(136, 32, 32, 255),
            new Color(24, 24, 24, 255)
        };

        public static Color[] ElectronColorList = new Color[]
        {
            new Color(0, 0, 0),
            new Color(255, 255, 255),
            new Color(0, 255, 255),
            new Color(255, 0, 0),
            new Color(0, 0, 255),
            new Color(255, 240, 0),
            new Color(0, 255, 0),
            new Color(255, 120, 0),
            new Color(255, 0, 255)
        };

        public static short[][] StairStates = new short[][]
        {
            new short[8] { 1,1,1,1,1,0,1,0 },
            new short[8] { 1,1,1,1,1,1,0,0 },
            new short[8] { 1,1,1,1,0,1,0,1 },
            new short[8] { 1,1,1,1,0,0,1,1 },
            new short[8] { 1,0,1,0,1,1,1,1 },
            new short[8] { 1,1,0,0,1,1,1,1 },
            new short[8] { 0,1,0,1,1,1,1,1 },
            new short[8] { 0,0,1,1,1,1,1,1 },
            new short[8] { 1,1,1,1,0,0,1,0 },
            new short[8] { 1,1,1,1,1,0,0,0 },
            new short[8] { 1,1,1,1,0,1,0,0 },
            new short[8] { 1,1,1,1,0,0,0,1 },
            new short[8] { 0,0,1,0,1,1,1,1 },
            new short[8] { 1,0,0,0,1,1,1,1 },
            new short[8] { 0,1,0,0,1,1,1,1 },
            new short[8] { 0,0,0,1,1,1,1,1 },
            new short[8] { 1,1,1,1,1,0,1,1 },
            new short[8] { 1,1,1,1,1,1,1,0 },
            new short[8] { 1,1,1,1,1,1,0,1 },
            new short[8] { 1,1,1,1,0,1,1,1 },
            new short[8] { 1,0,1,1,1,1,1,1 },
            new short[8] { 1,1,1,0,1,1,1,1 },
            new short[8] { 1,1,0,1,1,1,1,1 },
            new short[8] { 0,1,1,1,1,1,1,1 }
        };

        public static short[][] SlabStates = new short[][]
        {
            new short[8] { 1,1,1,1,0,0,0,0 },
            new short[8] { 0,0,0,0,1,1,1,1 }
        };

        //获取梯砖的值
        public static int GetStairValue(int value, int l)
        {
            int id = Terrain.ExtractContents(value);
            int data = Terrain.ExtractData(value);
            int? color = StairsBlock.GetColor(data);
            bool pass = (StairStates[StairsBlock.GetVariant(data)][l] == 1);
            switch (id)
            {
                case 49: id = 21; break;
                case 217: id = 3; break;
                case 48: id = 5; break;
                case 50: id = 26; break;
                case 76: id = 73; break;
                case 51: id = 4; break;
                case 69: id = 68; break;
                case 96: id = 67; break;
                default: return 0;
            }
            if (!pass) return 0;
            return (color.HasValue) ? Terrain.MakeBlockValue(id, 0, PaintedCubeBlock.SetColor(0, color.Value)) : id;
        }

        //获取半砖的值
        public static int GetSlabValue(int value, int l)
        {
            int id = Terrain.ExtractContents(value);
            int data = Terrain.ExtractData(value);
            int? color = SlabBlock.GetColor(data);
            bool pass = (SlabStates[SlabBlock.GetIsTop(data) ? 1 : 0][l] == 1);
            switch (id)
            {
                case 55: id = 21; break;
                case 136: id = 3; break;
                case 53: id = 5; break;
                case 54: id = 26; break;
                case 75: id = 73; break;
                case 52: id = 4; break;
                case 70: id = 68; break;
                case 95: id = 67; break;
                default: return 0;
            }
            if (!pass) return 0;
            return (color.HasValue) ? Terrain.MakeBlockValue(id, 0, PaintedCubeBlock.SetColor(0, color.Value)) : id;
        }

        //贴图颜色获取
        public static Color GetCommandColor(int color)
        {
            Color commandColor = Color.Green;
            switch (color)
            {
                case 0: commandColor = new Color(0, 255, 0); break;
                case 1: commandColor = new Color(181, 255, 255); break;
                case 2: commandColor = new Color(255, 181, 255); break;
                case 3: commandColor = new Color(160, 181, 255); break;
                case 4: commandColor = new Color(255, 240, 160); break;
                case 5: commandColor = new Color(181, 255, 181); break;
                case 6: commandColor = new Color(255, 181, 160); break;
                case 7: commandColor = new Color(181, 181, 181); break;
                case 8: commandColor = new Color(112, 112, 112); break;
                case 9: commandColor = new Color(0, 255, 255); break;
                case 10: commandColor = new Color(255, 0, 255); break;
                case 11: commandColor = new Color(0, 0, 255); break;
                case 12: commandColor = new Color(225, 112, 0); break;
                case 13: commandColor = new Color(0, 255, 0); break;
                case 14: commandColor = new Color(255, 0, 0); break;
                case 15: commandColor = new Color(24, 24, 24); break;
            }
            return commandColor;
        }

        //由颜色获取数据序号
        public static int GetColorIndex(Color c, int type = 0)
        {
            int index = 0;
            Color[] colorList = ColorList;
            if (type == 1) colorList = ElectronColorList;
            float[] arC = new float[colorList.Length];
            for (int i = 0; i < colorList.Length; i++)
            {
                Color c2 = colorList[i];
                //float cR = (c.R - c2.R) / 256f;
                //float cG = (c.G - c2.G) / 256f;
                //float cB = (c.B - c2.B) / 256f;
                //arC[i] = cR * cR + cG * cG + cB * cB;
                int r = (c.R + c2.R) / 2;
                int cR = (c.R - c2.R) * (c.R - c2.R);
                int cG = (c.G - c2.G) * (c.G - c2.G);
                int cB = (c.B - c2.B) * (c.B - c2.B);
                arC[i] = (2 + r / 256) * cR + 4 * cG + (2 + (255 - r) / 256) * cB;
            }
            float min = float.MaxValue;
            for (int k = 0; k < arC.Length; k++)
            {
                if (arC[k] < min)
                {
                    min = arC[k];
                    index = k;
                }
            }
            return index;
        }

        //数值转16进制信号
        public static string NumberToSignal(int n)
        {
            if (n < 10 && n >= 0) return n.ToString();
            else
            {
                switch (n)
                {
                    case 10: return "a";
                    case 11: return "b";
                    case 12: return "c";
                    case 13: return "d";
                    case 14: return "e";
                    case 15: return "f";
                    default: return "0";
                }
            }
        }

        //得到bool值
        public static bool GetBoolValue(string str)
        {
            return (str.ToLower() == "true");
        }

        //得到Vector2值
        public static Vector2 GetVector2Value(string str)
        {
            string[] arstr = str.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries);
            return new Vector2(int.Parse(arstr[0]), int.Parse(arstr[1]));
        }

        //得到Vector3值
        public static Vector3 GetVector3Value(string str)
        {
            string[] arstr = str.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries);
            return new Vector3(int.Parse(arstr[0]), int.Parse(arstr[1]), int.Parse(arstr[2]));
        }

        //得到Vector4值
        public static Vector4 GetVector4Value(string str)
        {
            string[] arstr = str.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries);
            return new Vector4(int.Parse(arstr[0]), int.Parse(arstr[1]), int.Parse(arstr[2]), int.Parse(arstr[3]));
        }

        //得到Point2值
        public static Point2 GetPoint2Value(string str)
        {
            string[] arstr = str.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries);
            return new Point2(int.Parse(arstr[0]), int.Parse(arstr[1]));
        }

        //得到Point3值
        public static Point3 GetPoint3Value(string str)
        {
            string[] arstr = str.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries);
            return new Point3(int.Parse(arstr[0]), int.Parse(arstr[1]), int.Parse(arstr[2]));
        }

        //得到Color值
        public static Color GetColorValue(string str)
        {
            string[] arstr = str.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries);
            if (arstr.Length == 3)
            {
                return new Color(int.Parse(arstr[0]), int.Parse(arstr[1]), int.Parse(arstr[2]));
            }
            else if (arstr.Length == 4)
            {
                return new Color(int.Parse(arstr[0]), int.Parse(arstr[1]), int.Parse(arstr[2]), int.Parse(arstr[3]));
            }
            else
            {
                return Color.White;
            }
        }

        //得到DateTime值
        public static DateTime GetDateTimeValue(string str)
        {
            string[] arstr = str.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries);
            int year = MathUtils.Clamp(int.Parse(arstr[0]), 2012, 2050);
            int month = MathUtils.Clamp(int.Parse(arstr[1]), 1, 12);
            int day = MathUtils.Clamp(int.Parse(arstr[2]), 1, 31);
            int hour = MathUtils.Clamp(int.Parse(arstr[3]), 0, 23);
            int minute = MathUtils.Clamp(int.Parse(arstr[4]), 0, 59);
            int second = MathUtils.Clamp(int.Parse(arstr[5]), 0, 59);
            return new DateTime(year, month, day, hour, minute, second);
        }

        //得到自然数
        public static int GetNaturalValue(string str)
        {
            int nv = int.Parse(str);
            return ((nv < 0) ? 0 : nv);
        }

        //特殊符转义
        public static string CharacterEscape(string str)
        {
            return str.Replace("[n]", "\n").Replace("[e]", " ").Replace("[c]", ":").Replace("[d]", "=");
        }

        //是否包含指令变量
        public static bool IsContainsVariable(string str)
        {
            List<string> constValues = new List<string>();
            string[] words = str.Split(new char[1] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
            foreach (string word in words)
            {
                string[] keyValue = word.Split(new char[1] { ':' }, StringSplitOptions.RemoveEmptyEntries);
                if (keyValue[0].Contains("fix") || keyValue[0].Contains("opt"))
                {
                    constValues.Add(keyValue[0] + ":" + keyValue[1]);
                }
            }
            if (constValues.Count != 0)
            {
                foreach (string c in constValues)
                {
                    str = str.Replace(c, "");
                }
            }
            return (str.Contains("X") || str.Contains("Y") || str.Contains("V") || str.Contains("W"));
        }

        //指令变量赋值
        public static CommandData SetVariableData(CommandData commandData, int[] signals)
        {
            foreach (string key in commandData.DataText.Keys)
            {
                try
                {
                    if (!IsContainsVariable(key + ":" + commandData.DataText[key])) continue;
                    commandData.Data[key] = ReplaceVariable(commandData.DataText[key], signals);
                    string[] arstr = ((string)commandData.Data[key]).Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                    if (arstr.Length > 1)
                    {
                        for (int l = 0; l < arstr.Length; l++)
                        {
                            if (IsExpression(arstr[l]))
                            {
                                arstr[l] = ExpressionHandle(arstr[l]);
                            }
                        }
                        commandData.Data[key] = string.Join(",", arstr);
                    }
                    else
                    {
                        if (IsExpression((string)commandData.Data[key]))
                        {
                            commandData.Data[key] = ExpressionHandle((string)commandData.Data[key]);
                        }
                    }
                }
                catch
                {
                }
            }
            commandData.FastSetValue();
            return commandData;
        }

        //字符串表达式处理
        public static string ExpressionHandle(string str)
        {
            string expression = str;
            int index = 0;
            string tempstr = "";
            TStack numStatck = new TStack();
            TStack operStatck = new TStack();
            while (true)
            {
                string ch = expression.Substring(index, 1);
                if (IsNum(ch))
                {
                    tempstr += ch;
                    if (index == expression.Length - 1 || !IsNum(expression.Substring(index + 1, 1)))
                    {
                        numStatck.Push(tempstr);
                    }
                }
                else
                {
                    tempstr = "";
                    if (operStatck.IsEmpty())
                    {
                        operStatck.Push(ch);
                    }
                    else
                    {
                        while (!operStatck.IsEmpty() && GetLevel(ch) <= GetLevel(operStatck.GetTop() + ""))
                        {
                            int res = Calculate(numStatck, operStatck);
                            numStatck.Push(res);
                        }
                        operStatck.Push(ch);
                    }
                }
                index++;
                if (index == expression.Length) break;
            }
            while (!operStatck.IsEmpty())
            {
                int res = Calculate(numStatck, operStatck);
                numStatck.Push(res);
            }
            double dnum = double.Parse(numStatck.Pop() + "");
            int inum = (int)MathUtils.Round(dnum);
            return inum + "";
        }

        //是否为表达式
        public static bool IsExpression(string str)
        {
            Regex regex = new Regex(@"^[0-9\+\-\*\/]+$");
            return !(string.IsNullOrEmpty(regex.Match(str).Value));
        }

        //数值替换变量
        public static string ReplaceVariable(string str, int[] ar)
        {
            char[] vc = { 'X', 'Y', 'V', 'W' };
            return str.Replace(vc[0] + "", ar[0] + "").Replace(vc[1] + "", ar[1] + "").Replace(vc[2] + "", ar[2] + "").Replace(vc[3] + "", ar[3] + "");
        }

        //是否为数字
        public static bool IsNum(string ch)
        {
            if (ch == "+" || ch == "-" || ch == "*" || ch == "/") return false;
            return true;
        }

        //符号优先级
        public static int GetLevel(String oper)
        {
            if ("*".Equals(oper) || "/".Equals(oper)) return 1;
            return 0;
        }

        //四则运算
        public static int Calculate(TStack numStatck, TStack operStatck)
        {
            int num1 = 0;
            if (numStatck.GetTop() != null)
            {
                num1 = int.Parse(numStatck.Pop() + "");
            }
            int num2 = 0;
            if (numStatck.GetTop() != null)
            {
                num2 = int.Parse(numStatck.Pop() + "");
            }
            string str = "";
            if (operStatck.GetTop() != null)
            {
                str = operStatck.Pop() + "";
            }
            int res = 0;
            switch (str.Substring(0, 1))
            {
                case "+": res = num1 + num2; break;
                case "-": res = num2 - num1; break;
                case "*": res = num1 * num2; break;
                case "/": res = num2 / num1; break;
            }
            return res;
        }

        //获取玩家眼睛角度
        public static Point2 GetPlayerEyesAngle(ComponentPlayer componentPlayer)
        {
            return DirectionToEyes(GetPlayerEyesDirection(componentPlayer));
            //int vx = (int)(componentPlayer.ComponentBody.Rotation.ToYawPitchRoll().X * 180f / 3.14f) + 180;
            //int vy = (int)(componentPlayer.ComponentLocomotion.LookAngles.Y * 180f / 3.14f) + 90;
            //return new Point2(vx, vy);
        }

        //获取玩家眼睛方向
        public static Vector3 GetPlayerEyesDirection(ComponentPlayer componentPlayer)
        {
            return componentPlayer.ComponentCreatureModel.EyeRotation.GetForwardVector();
        }

        //获取玩家身体方向
        public static Vector3 GetPlayerBodyDirection(ComponentPlayer componentPlayer)
        {
            return componentPlayer.ComponentBody.Matrix.Forward;
        }

        //获取实体所在方块的位置
        public static Point3 GetBodyPoint(ComponentBody componentBody)
        {
            int x = (int)MathUtils.Floor(componentBody.Position.X);
            int y = (int)MathUtils.Floor(componentBody.Position.Y);
            int z = (int)MathUtils.Floor(componentBody.Position.Z);
            return new Point3(x, y, z);
        }

        //由视角获取方向
        public static Vector3 EyesToDirection(Point2 eyes)
        {
            float horizontalAngle = (eyes.X - 180) / 180f * 3.14f;
            float verticalAngle = (eyes.Y - 90) / 180f * 3.14f;
            float y = MathUtils.Sin(verticalAngle);
            float z = -MathUtils.Cos(horizontalAngle) * MathUtils.Cos(verticalAngle);
            float x = -MathUtils.Sin(horizontalAngle) * MathUtils.Cos(verticalAngle);
            Vector3 direction = new Vector3(x, y, z);
            return direction / direction.Length();
        }

        //由方向获取视角
        public static Point2 DirectionToEyes(Vector3 direction)
        {
            float ay = MathUtils.Asin(direction.Y / direction.Length());
            float ax = MathUtils.Acos(direction.Z / direction.XZ.Length());
            int xangle = (int)(ax * 180f / 3.14f) + 1;
            if (direction.X < 0) xangle = 360 - xangle;
            int yangle = (int)(ay * 180f / 3.14f) + 90;
            return new Point2(xangle, yangle);
        }

        //视角相加
        public static Point2 EyesAdd(Point2 eyes1, Point2 eyes2)
        {
            Point2 addEyes = eyes1 + eyes2;
            addEyes.X = addEyes.X % 360;
            if (addEyes.Y > 180) addEyes.Y = 180;
            if (addEyes.Y < 0) addEyes.Y = 0;
            return addEyes;
        }

        //获取命令方块资源路径
        public static string GetCommandPath()
        {
            string path = (Environment.CurrentDirectory == "/") ? "android:SurvivalCraft2.3" : "app:";
            string commandPath = Storage.CombinePaths(path, "Command");
            if (!Storage.DirectoryExists(commandPath)) Storage.CreateDirectory(commandPath);
            return commandPath;
        }

        //获取命令方块资源文件路径
        public static string GetCommandResPathName(string pathName)
        {
            if (GameManager.m_worldInfo != null)
            {
                string worldPath = GameManager.m_worldInfo.DirectoryName;
                if (Storage.FileExists(Storage.CombinePaths(worldPath, pathName)))
                {
                    return Storage.CombinePaths(worldPath, pathName);
                }
            }
            string path = (Environment.CurrentDirectory == "/") ? "android:SurvivalCraft2.3" : "app:";
            string commandPath = Storage.CombinePaths(path, "Command");
            if (!Storage.DirectoryExists(commandPath)) Storage.CreateDirectory(commandPath);
            return Storage.CombinePaths(commandPath, pathName);
        }

        //删除指定文件夹所有文件
        public static void DeleteAllFile(string path)
        {
            foreach (string name in Storage.ListFileNames(path))
            {
                Storage.DeleteFile(Storage.CombinePaths(path, name));
            }
            foreach (string dir in Storage.ListDirectoryNames(path))
            {
                DeleteAllFile(Storage.CombinePaths(path, dir));
            }
        }

        //删除指定文件夹
        public static void DeleteAllDirectory(string path)
        {
            foreach (string dir in Storage.ListDirectoryNames(path))
            {
                DeleteAllDirectory(Storage.CombinePaths(path, dir));
            }
            if (Storage.ListDirectoryNames(path).Count() == 0)
            {
                Storage.DeleteDirectory(path);
            }
        }

        //删除指定路径所有文件包括本身
        public static void DeleteAllDirectoryAndFile(string path)
        {
            DeleteAllFile(path);
            DeleteAllDirectory(path);
        }

        //新的射线投影
        public static object Raycast(Ray3 ray, ComponentMiner componentMiner)
        {
            float reach = 500f;
            Vector3 creaturePosition = componentMiner.ComponentCreature.ComponentCreatureModel.EyePosition;
            Vector3 start = ray.Position;
            var direction = Vector3.Normalize(ray.Direction);
            Vector3 end = ray.Position + direction * 500f;
            Point3 startCell = Terrain.ToCell(start);
            BodyRaycastResult? bodyRaycastResult = componentMiner.m_subsystemBodies.Raycast(start, end, 0.35f, (ComponentBody body, float distance) =>
            {
                bool flag = Vector3.DistanceSquared(start + distance * direction, creaturePosition) <= reach * reach;
                bool flag2 = body.Entity != componentMiner.Entity && !body.IsChildOfBody(componentMiner.ComponentCreature.ComponentBody) && !componentMiner.ComponentCreature.ComponentBody.IsChildOfBody(body);
                bool flag3 = Vector3.Dot(Vector3.Normalize(body.BoundingBox.Center() - start), direction) > 0.7f;
                return (flag && flag2 && flag3) ? true : false;
            });
            MovingBlocksRaycastResult? movingBlocksRaycastResult = componentMiner.m_subsystemMovingBlocks.Raycast(start, end, extendToFillCells: true);
            TerrainRaycastResult? terrainRaycastResult = componentMiner.m_subsystemTerrain.Raycast(start, end, useInteractionBoxes: true, skipAirBlocks: true, delegate (int value, float distance)
            {
                return true;
            });
            float num = bodyRaycastResult.HasValue ? bodyRaycastResult.Value.Distance : float.PositiveInfinity;
            float num2 = movingBlocksRaycastResult.HasValue ? movingBlocksRaycastResult.Value.Distance : float.PositiveInfinity;
            float num3 = terrainRaycastResult.HasValue ? terrainRaycastResult.Value.Distance : float.PositiveInfinity;
            if (num < num2 && num < num3)
            {
                return bodyRaycastResult.Value;
            }
            if (num2 < num && num2 < num3)
            {
                return movingBlocksRaycastResult.Value;
            }
            if (num3 < num && num3 < num2)
            {
                return terrainRaycastResult.Value;
            }
            return new Ray3(start, direction);
        }
    }
}